package com.ymt.fmd.util;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ymt.fmd.platform.dao.mysql.CustomSQLDao;
import com.ymt.fmd.platform.dao.mysql.PI18nMapper;
import com.ymt.fmd.platform.model.PI18n;

/**
 * Util for meta data operations
 * @author fuzheng
 *
 */
public class MetaDataUtil {
	
	//data type
	public static final String TYPE = "Type";
	//number type
	public static final String TYPE_NUMBER = "Number";
	//date type
	public static final String TYPE_DATE = "Date";
	//string type
	public static final String TYPE_STRING = "String";
	//value
	public static final String VALUE = "value";
	//dataprovider
	public static final String DP = "DATAPROVIDER";
	//dataprovider type
	public static final String DP_TYPE = "TYPE";
	//dataprovider type enumeration
	public static final String DP_TYPE_ENUMERATION = "ENUMERATION";
	//dataprovider type custom enumeration
	public static final String DP_TYPE_CUSTOMENUM = "CUSTOMENUMERATION";
	//dataprovider type bilingual
	public static final String DP_TYPE_BILINGUAL = "BILINGUAL";
	//dataprovider type popup selector
	public static final String DP_TYPE_POPUPSELECTOR = "POPUPSELECTOR";
	//dataprovider type custom enumeration - table
	public static final String DP_CUSTOMENUM_TABLE = "TABLE";
	//dataprovider type custom enumeration - value column
	public static final String DP_CUSTOMENUM_VALUECOLUMN = "VALUECOLUMN";
	//dataprovider type custom enumeration - display column
	public static final String DP_CUSTOMENUM_DISPLAYVALUECOLUMN = "DISPLAYVALUECOLUMN";
	//dataprovider type custom enumeration - where clause
	public static final String DP_CUSTOMENUM_WHERE = "WHERE";
	//dataprovider type custom enumeration - order by
	public static final String DP_CUSTOMENUM_ORDERBY = "ORDERBY";
	//dataprovider type custom enumeration - lang
	public static final String DP_CUSTOMENUM_LANGVAR = "${LANG}";
	//dataprovider type custom enumeration - i18n target
	public static final String DP_ENUMERATION_I18NTARGET = "I18NTARGET";
	//dataprovider type custom enumeration - i18n type
	public static final String DP_ENUMERATION_I18NTYPE = "I18NTYPE";
	
	/**
	 * Enumeration type tag
	 */
	public static final String I18N = "I18N";
	/**
	 * Enumeration type tag in i18n
	 */
	public static final String I18N_CATEGORY_ENUM = DP_TYPE_ENUMERATION;
	/**
	 * METADATA type tag in i18n
	 */
	public static final String I18N_CATEGORY_METADATA = "METADATA";
	/**
	 * ecsbpm target type tag in i18n
	 */
	public static final String I18N_TARGET_BPM = "BPM";
	/**
	 * ssc target type tag in i18n
	 */
	public static final String I18N_TARGET_SSC = "SSC";
	
	/**
	 * static logger
	 */
	private static Logger logger = Logger.getLogger(MetaDataUtil.class.getName());

	/**
	 * get i18n info for a specific type in json format
	 * @param iDao
	 * @param target
	 * @param category
	 * @param type
	 * @param lang
	 * @return
	 */
	public static JSONObject getI18nJson(PI18nMapper iDao, String target, String category, String type, String lang) {
		PI18n i18n = new PI18n();
		i18n.setTarget(target);
		i18n.setCategory(category);
		i18n.setLang(lang);
		i18n.setType(type);
		List<PI18n> list = iDao.selectByObject(i18n);
		if (list==null || list.size()==0) {
			return null;
		}
		JSONObject js = new JSONObject();
		for (PI18n i:list) {
			js.put(i.getRelationkey(), i.getValue());
		}
		return js;
	}

	/**
	 * get i18n info for a specific type in json format
	 * @param iDao
	 * @param target
	 * @param category
	 * @param type
	 * @param lang
	 * @return
	 */
	public static JSONArray getI18nJsarray(PI18nMapper iDao, String target, String category, String type, String lang) {
		PI18n i18n = new PI18n();
		i18n.setTarget(target);
		i18n.setCategory(category);
		i18n.setLang(lang);
		i18n.setType(type);
		List<PI18n> list = iDao.selectByObject(i18n);
		if (list==null || list.size()==0) {
			return null;
		}
		JSONArray jsa = new JSONArray();
		for (PI18n i:list) {
			JSONArray ja = new JSONArray();
			ja.add(i.getRelationkey());
			ja.add(i.getValue());
			jsa.add(ja);
		}
		return jsa;
	}

	/**
	 * get i18n info for a specific type in json format
	 * @param iDao
	 * @param dpJo
	 * @param lang
	 * @return
	 */
	public static JSONObject getI18nJson(PI18nMapper iDao, JSONObject dpJo, String lang) {
		return getI18nJson(iDao, 
				dpJo.getString(DP_ENUMERATION_I18NTARGET), 
				MetaDataUtil.I18N_CATEGORY_ENUM, dpJo.getString(DP_ENUMERATION_I18NTYPE), lang);
	}

	/**
	 * get i18n info for a specific type in json format
	 * @param iDao
	 * @param dpJo
	 * @param lang
	 * @return
	 */
	public static JSONArray getI18nJsarray(PI18nMapper iDao, JSONObject dpJo, String lang) {
		return getI18nJsarray(iDao, 
				dpJo.getString(DP_ENUMERATION_I18NTARGET), 
				MetaDataUtil.I18N_CATEGORY_ENUM, dpJo.getString(DP_ENUMERATION_I18NTYPE), lang);
	}
		
	/**
	 * format value by format predefined in ts_tablecolumnmeta
	 * @param f
	 * @param val
	 * @return
	 */
	public static String formatValue(Object val, String f, String lang, int timezoneoffset) {
		if (val==null) {
			return null;
		}
		if (val instanceof java.math.BigDecimal) {
			return val.toString();
		} else if (val instanceof java.sql.Timestamp) {
			Date d = new Date(((java.sql.Timestamp)val).getTime());
			if (f!=null && f.length()>0) {
				return DateUtil.formatDate(d, f, timezoneoffset);
			}
			return DateUtil.formatDate(d, DateUtil.getSSFormatByLang(lang), timezoneoffset);
		} else {
			return val.toString();
		}
	}
	
	/**
	 * Parse data provider and put into a json
	 * @param csDao
	 * @param containerJo
	 * @param dpVal
	 */
	public static void putParsedDataProviderByType(String tenantId, CustomSQLDao csDao, PI18nMapper iDao, JSONObject containerJo, String dpVal, String lang) {
		logger.finest("putParsedDataProviderByType dpVal="+dpVal);
		JSONObject dpJo = JSONObject.parseObject(dpVal);
		String type = dpJo.getString(DP_TYPE);
		if (DP_TYPE_CUSTOMENUM.equalsIgnoreCase(type)) {
			JSONObject newDpJo = new JSONObject();
			newDpJo.put(MetaDataUtil.DP_TYPE_ENUMERATION, getCustomEnumerationJsArray(tenantId, csDao, dpJo, lang));
			newDpJo.put(MetaDataUtil.DP_TYPE, MetaDataUtil.DP_TYPE_ENUMERATION);
			containerJo.put(MetaDataUtil.DP, newDpJo);
		} else if (DP_TYPE_ENUMERATION.equalsIgnoreCase(type)) {
			JSONObject newDpJo = new JSONObject();
			newDpJo.put(MetaDataUtil.DP_TYPE_ENUMERATION, getI18nJsarray(iDao, dpJo.getString(DP_ENUMERATION_I18NTARGET), 
					I18N_CATEGORY_ENUM, dpJo.getString(DP_ENUMERATION_I18NTYPE), lang));
			newDpJo.put(MetaDataUtil.DP_TYPE, MetaDataUtil.DP_TYPE_ENUMERATION);
			containerJo.put(MetaDataUtil.DP, newDpJo);
		} else {
			containerJo.put(DP, MetaDataUtil.serversUriReplace(dpVal));
		}
	}

	/**
	 * Parse data provider that type is CUSTOMENUMERATION
	 * @param tenantId
	 * @param csDao
	 * @param jo
	 * @param lang
	 * @return
	 */
	public static JSONObject getCustomEnumerationJson(String tenantId, CustomSQLDao csDao, JSONObject jo, String lang) {
		List<Map<String,?>> list = getCustomEnumerationList(tenantId, csDao, jo, lang);
		JSONObject rtn = new JSONObject();
		for (Map<String,?> map:list) {
			rtn.put((String)map.get(jo.getString(DP_CUSTOMENUM_VALUECOLUMN)),
					map.get(jo.getString(DP_CUSTOMENUM_DISPLAYVALUECOLUMN)));
		}
		logger.finest("getCustomEnumerationJson rtn="+rtn.toString());
		return rtn;
	}

	/**
	 * Parse data provider that type is CUSTOMENUMERATION
	 * @param tenantId
	 * @param csDao
	 * @param jo
	 * @param lang
	 * @return
	 */
	public static JSONArray getCustomEnumerationJsArray(String tenantId, CustomSQLDao csDao, JSONObject jo, String lang) {
		List<Map<String,?>> list = getCustomEnumerationList(tenantId, csDao, jo, lang);
		JSONArray rtn = new JSONArray();
		for (Map<String,?> map:list) {
			JSONArray ja = new JSONArray();
			ja.add(map.get(jo.getString(DP_CUSTOMENUM_VALUECOLUMN)));
			ja.add(map.get(jo.getString(DP_CUSTOMENUM_DISPLAYVALUECOLUMN)));
			rtn.add(ja);
		}
		logger.finest("getCustomEnumerationJsArray rtn="+rtn.toString());
		return rtn;
	}

	/**
	 * Parse data provider that type is CUSTOMENUMERATION
	 * @param tenantId
	 * @param csDao
	 * @param jo
	 * @param lang
	 * @return
	 */
	public static List<Map<String,?>> getCustomEnumerationList(String tenantId, CustomSQLDao csDao, JSONObject jo, String lang) {
		StringBuilder sql = new StringBuilder(Operator.SQL_SELECT);
		String where = jo.getString(DP_CUSTOMENUM_WHERE);
		String orderby = jo.getString(DP_CUSTOMENUM_ORDERBY);
		sql.append(jo.getString(DP_CUSTOMENUM_VALUECOLUMN) + Operator.COMMA + jo.getString(DP_CUSTOMENUM_DISPLAYVALUECOLUMN));
		sql.append(Operator.SQL_FROM);
		sql.append(Operator.QUOTEL + jo.getString(DP_CUSTOMENUM_TABLE) + Operator.QUOTER);
		if (where!=null && where.length()>0) {
			sql.append(Operator.SQL_WHERE);
			where = where.replace(DP_CUSTOMENUM_LANGVAR, lang);
			sql.append(where);
			if (tenantId!=null) {
				sql.append(" AND TENANT_ID=");
				sql.append(tenantId);
			}
		} else {
			if (tenantId!=null) {
				sql.append(" WHERE TENANT_ID=");
				sql.append(tenantId);
			}
		}
		if (orderby!=null && orderby.length()>0) {
			sql.append(Operator.SQL_ORDERBY);
			sql.append(orderby);
		}
		logger.finest("getCustomEnumerationList sql="+sql);
		List<Map<String,?>> list = csDao.select(sql.toString());
		logger.finest("getCustomEnumerationList list="+list);
		return list;
	}
	
	/**
	 * replace server url in string
	 * @param str
	 * @return
	 */
	public static String serversUriReplace(String str) {
		if (str==null) {
			return null;
		}
		//newstr =  replaceVar(newstr, Const.URL_SERVER_BPM);
		return str;
	}
	
	/**
	 * replace variable with value in string
	 * @param str
	 * @param var
	 * @return
	 */
	public static String replaceVar(String str, String var, String val) {
		if (str==null) {
			return null;
		}
		String pre = "${";
		String suf = "}";
		return str.replace(pre+var+suf, val);
	}

}
